﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Threading;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Windows.Navigation;

namespace VISUALFINDR
{
    public partial class VisualSearchPage : PhoneApplicationPage
    {
        private Timer uploadTimer;
        private Timer pollTimer;
        
        public VisualSearchPage()
        {
            InitializeComponent();

            imageVisualSearch.Source = App.CapturedImage;

            if (App.uploadController.shouldUpload())
                StartVisualSearchUpload();
            else
            {
                if (App.pollingController.shouldPoll())
                    StartVisualSearchPoll();
                else
                    FinishedVisualSearchPoll();
            }
        }

        /*
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
           
        }
         * */

        /*
        protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
        {
            doReload = false;
            //e.Cancel = true;
        }*/

        // Visual Search Upload
        public void StartVisualSearchUpload()
        {
            byte[] imageData = HistoryController.LoadIfExists();
            if (imageData == null)
                textBlockStatus.Text = "Upload Failed, image doesnt exist";
            else
            {
                textBlockStatus.Text = "Upload starting...";
                App.uploadController.UploadImagePhone(imageData);
                uploadTimer = new Timer(new TimerCallback(UploadTimerTicked), null, 0, 2000);
            }
        }

        
        public static void UIInvokeSync(Action a)
        {
            if (System.Windows.Deployment.Current.Dispatcher.CheckAccess())
            {
                a(); // meaning this is already the UI thread so just do it;
            }
            else
            {
                ManualResetEvent e = new ManualResetEvent(false);
                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => { a(); e.Set(); });
                e.WaitOne();
            }
        }

        public void UploadTimerTicked(Object stateInfo)
        {
            String latestResponse = App.uploadController.LatestResponse;
            if (latestResponse != null && latestResponse.Length > 0)
            {
                uploadTimer.Dispose();
                if (latestResponse == "Failed")
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(FailedVisualSearchUpload);
                else
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(FinishedVisualSearchUpload);
            }            
        }

        public void FinishedVisualSearchUpload()
        {
            // Update UI to reflect changes
            textBlockStatus.Text = "Upload Finished, starting poll";
            checkBoxUploaded.IsChecked = true;
            
            // GOGOGO
            StartVisualSearchPoll();
        }

        public void FailedVisualSearchUpload()
        {
            textBlockStatus.Text = "Upload Failed, try again later";
        }

        // Visual Search Polling
        public void StartVisualSearchPoll()
        {
            checkBoxUploaded.IsChecked = true;
            App.pollingController.ForceReset();

            pollTimer = new Timer(new TimerCallback(PollTimerTicked), null, 0, 1000);
        }

        public void PollTimerTicked(Object stateInfo)
        {
            String latestResponse = App.pollingController.LatestResponse;
            bool lastAct = false;
            if (latestResponse != null && latestResponse.Length > 0)
            {
                // Check status of response first:
                String status = App.pollingController.Status(latestResponse);
                if (status == "waiting")
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(WaitingVisualSearchPoll);
                else if (status == "in progress")
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(InProgressVisualSearchPoll);
                else if (status == "matched" || status == "unrecognised")
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(FinishedVisualSearchPoll);
                else
                {
                    lastAct = true;
                    pollTimer.Dispose();
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(FailedVisualSearchPoll);
                }
            }

            if (!lastAct)
            {
                if (App.pollingController.shouldPoll())
                {
                    String searchId = App.uploadController.SearchId();
                    App.pollingController.GetSearchIdStatusPhone(searchId);
                }
                else
                {
                    pollTimer.Dispose();
                }
            }
        }

        bool waitingSwitch = false;
        public void WaitingVisualSearchPoll()
        {
            if (waitingSwitch)
            {
                waitingSwitch = false;
                textBlockStatus.Text = "Waiting...";
            }
            else
            {
                waitingSwitch = true;
                textBlockStatus.Text = "Still waiting...";
            }
        }

        bool inProgressSwitch = false;
        public void InProgressVisualSearchPoll()
        {
            if (inProgressSwitch)
            {
                inProgressSwitch = false;
                textBlockStatus.Text = "In progresss...";
            }
            else
            {
                inProgressSwitch = true;
                textBlockStatus.Text = "Still in progress";
            }
        }

        public void FinishedVisualSearchPoll()
        {
            textBlockStatus.Text = "Polling Finished";
            checkBoxCompleted.IsChecked = true;
            checkBoxUploaded.IsChecked = true;

            String status = App.pollingController.Status();
            if (status == "matched")
            {
                textBlockStatus.Text = "Image was matched";
                buttonCheckItOut.Visibility = Visibility.Visible;
                MakeBingSearch();
            }
            else if (status == "unrecognised")
                textBlockStatus.Text = "No matches found";
            else if (status == "Failed")
                FailedVisualSearchPoll();
            else
                textBlockStatus.Text = "Shouldnt be here, ever";
        }

        public void FailedVisualSearchPoll()
        {
            textBlockStatus.Text = "Polling Failed, try again later";
            checkBoxCompleted.IsChecked = false;
            buttonRetry.Visibility = Visibility.Visible;
        }

        private void buttonCheckItOut_Click(object sender, RoutedEventArgs e)
        {
            //NavigationService.Navigate(new Uri("/VisualSearchResultPage.xaml", UriKind.Relative));
            MakeBingSearch();
        }

        void MakeBingSearch()
        {
            //String jsonStringRaw = "{\"d\":{\"__type\":\"APISearchStatus:#Cortexica.API\",\"Count\":\"20\",\"Objects\":[{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Moore Albert\",\"Id\":\"190905\",\"Metadata\":[{\"__type\":\"APIObjectMetadata:#Cortexica.API\",\"Key\":\"Artist\",\"Value\":\"Moore Albert\"},{\"__type\":\"APIObjectMetadata:#Cortexica.API\",\"Key\":\"Title\",\"Value\":\"A Summer Night\"}],\"Name\":\"A Summer Night\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"leaves.jpg\",\"Id\":\"187693\",\"Metadata\":[],\"Name\":\"leaves.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Basket_of_Flowers_CGF.jpg\",\"Id\":\"154056\",\"Metadata\":[],\"Name\":\"Basket_of_Flowers_CGF.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"The_Woodcutters_Return.jpg\",\"Id\":\"181774\",\"Metadata\":[],\"Name\":\"The_Woodcutters_Return.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Odilon_Redon_(40).jpg\",\"Id\":\"174039\",\"Metadata\":[],\"Name\":\"Odilon_Redon_(40).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Cox_David_Shipping_On_The_Sheldt_Dort_Church_In_The_Distance.jpg\",\"Id\":\"158117\",\"Metadata\":[],\"Name\":\"Cox_David_Shipping_On_The_Sheldt_Dort_Church_In_The_Distance.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Benvenuto_Benvenuti_(59).jpg\",\"Id\":\"154333\",\"Metadata\":[],\"Name\":\"Benvenuto_Benvenuti_(59).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"GOLTZIUS_Hendrick_The_Rich_Kitchen.jpg\",\"Id\":\"162419\",\"Metadata\":[],\"Name\":\"GOLTZIUS_Hendrick_The_Rich_Kitchen.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Harlamoff_Alexej_Auburn_haired_Beauty_with_Bouquet_of_Roses.jpg\",\"Id\":\"164820\",\"Metadata\":[],\"Name\":\"Harlamoff_Alexej_Auburn_haired_Beauty_with_Bouquet_of_Roses.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Luis_Miguel_Doyague_(45).jpg\",\"Id\":\"170595\",\"Metadata\":[],\"Name\":\"Luis_Miguel_Doyague_(45).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Sisley_Alfred_Windy_Day_At_Veneux.jpg\",\"Id\":\"179918\",\"Metadata\":[],\"Name\":\"Sisley_Alfred_Windy_Day_At_Veneux.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Don%20Juan%20Discovered%20by%20Haydee.jpg\",\"Id\":\"159218\",\"Metadata\":[],\"Name\":\"Don%20Juan%20Discovered%20by%20Haydee.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Bierstadt_Albert_Estes_Park_Colorado.jpg\",\"Id\":\"154529\",\"Metadata\":[],\"Name\":\"Bierstadt_Albert_Estes_Park_Colorado.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Henri_Rousseau_(59).jpg\",\"Id\":\"165276\",\"Metadata\":[],\"Name\":\"Henri_Rousseau_(59).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"River_landscape_EUR.jpg\",\"Id\":\"178481\",\"Metadata\":[],\"Name\":\"River_landscape_EUR.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"On_the_Banks_of_the_Bosphorus.jpg\",\"Id\":\"174130\",\"Metadata\":[],\"Name\":\"On_the_Banks_of_the_Bosphorus.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Gino_Covili_(62).jpg\",\"Id\":\"163515\",\"Metadata\":[],\"Name\":\"Gino_Covili_(62).jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Fyt_Jan_A_Peacock_In_A_Landscape_With_Roosters_Turkeys_Ducks_A_Heron_And_A_Parrot.jpg\",\"Id\":\"162255\",\"Metadata\":[],\"Name\":\"Fyt_Jan_A_Peacock_In_A_Landscape_With_Roosters_Turkeys_Ducks_A_Heron_And_A_Parrot.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Winter_The_Snowstorm_CGF.jpg\",\"Id\":\"183638\",\"Metadata\":[],\"Name\":\"Winter_The_Snowstorm_CGF.jpg\",\"Type\":\"\",\"Url\":\"\"},{\"__type\":\"APIObjectInfo:#Cortexica.API\",\"Brief\":\"Gloria_Torner_(32).jpg\",\"Id\":\"163815\",\"Metadata\":[],\"Name\":\"Gloria_Torner_(32).jpg\",\"Type\":\"\",\"Url\":\"\"}],\"Status\":\"matched\"}}";
            String jsonStringRaw = App.pollingController.LatestResponse;
            String jsonString = App.pollingController.CleanJsonResponse(jsonStringRaw);
            PollResponseDictionary d = new PollResponseDictionary();
            MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
            DataContractJsonSerializer serializer = new DataContractJsonSerializer(d.GetType());
            d = serializer.ReadObject(ms) as PollResponseDictionary;
            ms.Close();

            APIObject apiObject = d.d.Objects.First();
            App.UpdateText(apiObject.Name);
            UriBuilder fullUri = new UriBuilder("http://bing.com/search?q=" + apiObject.Name);//"&go=&form=QBLH&filt=all&qs=n&sk=&sc=8-4");
            NavigationService.Navigate(new Uri("/BingBrowserPage.xaml?url=" + fullUri, UriKind.Relative));
        }

        private void buttonRetry_Click(object sender, RoutedEventArgs e)
        {
            buttonRetry.Visibility = Visibility.Collapsed;

            imageVisualSearch.Source = App.CapturedImage;

            App.pollingController.ForceReset();

            if (App.uploadController.shouldUpload())
                StartVisualSearchUpload();
            else
            {
                if (App.pollingController.shouldPoll())
                    StartVisualSearchPoll();
                else
                    FinishedVisualSearchPoll();
            }
        }
    }
}